package com.ruoyi.waterDistribution.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.core.constant.BusinessConstants;
import com.ruoyi.common.core.domain.business.waterDistribution.WiFarmplanM;
import com.ruoyi.common.core.domain.business.waterDistribution.WiOrgplanM;
import com.ruoyi.common.core.domain.business.waterDistribution.WiPeriodY;
import com.ruoyi.common.core.enums.TenEnum;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.business.BusinessUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.waterDistribution.mapper.WiFarmplanMMapper;
import com.ruoyi.waterDistribution.mapper.WiOrgplanMMapper;
import com.ruoyi.waterDistribution.mapper.WiPeriodYMapper;
import com.ruoyi.waterDistribution.service.IWiFarmplanMService;
import com.ruoyi.waterDistribution.vo.WiLandBVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 月农户限额水量及计划水量计算Service业务层处理
 * 
 * @author ps
 * @date 2023-02-16
 */
@Service
public class WiFarmplanMServiceImpl implements IWiFarmplanMService {

    private static final Logger log = LoggerFactory.getLogger(WiFarmplanMServiceImpl.class);

    @Autowired
    private WiFarmplanMMapper wiFarmplanMMapper;
    @Autowired
    private WiOrgplanMMapper wiOrgplanMMapper;
    @Autowired
    private WiPeriodYMapper wiPeriodYMapper;


    /**
     * 查询月农户限额水量及计划水量计算
     * 
     * @param farmCd 月农户限额水量及计划水量计算主键
     * @return 月农户限额水量及计划水量计算
     */
    @Override
    public WiFarmplanM selectWiFarmplanMByFarmCd(String farmCd)
    {
        return wiFarmplanMMapper.selectWiFarmplanMByFarmCd(farmCd);
    }

    /**
     * 查询月农户限额水量及计划水量计算列表
     * 
     * @param wiFarmplanM 月农户限额水量及计划水量计算
     * @return 月农户限额水量及计划水量计算
     */
    @Override
    public List<WiFarmplanM> selectWiFarmplanMList(WiFarmplanM wiFarmplanM)
    {
        return wiFarmplanMMapper.selectWiFarmplanMList(wiFarmplanM);
    }

    /**
     * 新增月农户限额水量及计划水量计算
     * 
     * @param wiFarmplanM 月农户限额水量及计划水量计算
     * @return 结果
     */
    @Override
    public int insertWiFarmplanM(WiFarmplanM wiFarmplanM)
    {
        return wiFarmplanMMapper.insertWiFarmplanM(wiFarmplanM);
    }

    /**
     * 修改月农户限额水量及计划水量计算
     * 
     * @param wiFarmplanM 月农户限额水量及计划水量计算
     * @return 结果
     */
    @Override
    public int updateWiFarmplanM(WiFarmplanM wiFarmplanM)
    {
        return wiFarmplanMMapper.updateWiFarmplanM(wiFarmplanM);
    }

    /**
     * 批量删除月农户限额水量及计划水量计算
     * 
     * @param farmCds 需要删除的月农户限额水量及计划水量计算主键
     * @return 结果
     */
    @Override
    public int deleteWiFarmplanMByFarmCds(String[] farmCds)
    {
        return wiFarmplanMMapper.deleteWiFarmplanMByFarmCds(farmCds);
    }

    /**
     * 删除月农户限额水量及计划水量计算信息
     * 
     * @param farmCd 月农户限额水量及计划水量计算主键
     * @return 结果
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public int deleteWiFarmplanMByFarmCdAndPlanYm(String farmCd,String planYm)
    {
        return wiFarmplanMMapper.deleteWiFarmplanMByFarmCdAndPlanYm(farmCd,planYm);
    }

    /**
     * 汇总农户旬用水计划
     * @param farmCd
     * @param year
     * @return
     */
    @Override
    public int setTenPlan(String year, String farmCd) throws Exception {
        /**返回数据定义 start*/
        ArrayList<HashMap<String, Object>> resList = new ArrayList<>();
        BigDecimal ten1;//上旬水量
        BigDecimal ten2;//中旬水量
        BigDecimal ten3;//下旬水量
        BigDecimal monthSum;//月水量
        /**返回数据定义 new*/
        List<WiLandBVo> WiLandBVoList = this.getWiLandBListByFarmCd(year, farmCd);
        //将所有地块按作物分组求面积和
        Map<String, Double> collect = WiLandBVoList.parallelStream().collect(Collectors.groupingBy(WiLandBVo::getCropCd,
                Collectors.summingDouble(s -> Double.valueOf(s.getLandSize() == null ? "0" : s.getLandSize() + ""))));
        //遍历12个月
        for (String monthStr : BusinessConstants.MONTHS) {
//            if (!monthStr.equals("02")) {
//                continue;
//            }
            //每月变量清零
            HashMap<String, Object> resMap = new HashMap<>();
            ten1 = new BigDecimal("0");//上旬水量
            ten2 = new BigDecimal("0");//中旬水量
            ten3 = new BigDecimal("0");//下旬水量
            monthSum = new BigDecimal("0");//月水量
            //遍历作物-地块面积和
            for (Map.Entry<String, Double> entry : collect.entrySet()) {
                log.info("作物代码：" + entry.getKey() + "=地块面积：" + entry.getValue());
                List<WiPeriodY> wiPeriodYList = wiPeriodYMapper.selectWiPeriodListbyCropAndCropCd(year, entry.getKey());
                //遍历周期定额
                for (WiPeriodY wiPeriodY : wiPeriodYList) {
                    for (HashMap<String, String> tensMap : BusinessConstants.TENSLIST) {
                        BigDecimal periodVol = wiPeriodY.getPeriodVol() == null ? new BigDecimal("0") : wiPeriodY.getPeriodVol();
                        String beginDate = DateUtils.dateTime(wiPeriodY.getBeginDate());
                        String endDate = DateUtils.dateTime(wiPeriodY.getEndDate());
                        String beginDate2 = year + "-" + monthStr + "-" + tensMap.get("tenStart");
                        String endDate2 = year + "-" + monthStr + "-" + tensMap.get("tenEnd");
                        //动态调整当月最后一天
                        if (tensMap.get("tenEnd").equals("31")) {
                            endDate2 = BusinessUtils.getMonthLastday(year, monthStr);
                        }
                        int i = BusinessUtils.differentDaysByMillisecond(wiPeriodY.getBeginDate(), wiPeriodY.getEndDate());
                        int days = BusinessUtils.getDays(beginDate, endDate, beginDate2, endDate2);
                        log.info("周期定额：" + beginDate + "=" + endDate);
                        log.info("旬分区：" + beginDate2 + "=" + endDate2);
                        log.info("包含天数：" + days);
                        log.info("周期定额包含天数：" + i + " 周期定额为：" + periodVol);
                        log.info(" 定额按比例计算结果：" + periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2));
                        log.info(" 地块旬定额水量：" + new BigDecimal(entry.getValue()).multiply(periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2)));
                        //上旬
                        if (TenEnum.TEN1.getCode().equals(tensMap.get("ten1"))) {
                            ten1 = ten1.add(new BigDecimal(entry.getValue()).multiply(periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2)));
                        }
                        //中旬
                        if (TenEnum.TEN2.getCode().equals(tensMap.get("ten2"))) {
                            ten2 = ten2.add(new BigDecimal(entry.getValue()).multiply(periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2)));
                        }
                        //下旬
                        if (TenEnum.TEN3.getCode().equals(tensMap.get("ten3"))) {
                            ten3 = ten3.add(new BigDecimal(entry.getValue()).multiply(periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2)));
                        }
                        monthSum = monthSum.add(new BigDecimal(entry.getValue()).multiply(periodVol.multiply(new BigDecimal(days).divide(new BigDecimal(i), 2, BigDecimal.ROUND_DOWN)).setScale(2)));
                    }
                }
            }
            //将旬放入
            resMap.put("month", monthStr);
            resMap.put("ten1", ten1);
            resMap.put("ten2", ten2);
            resMap.put("ten3", ten3);
            resMap.put("monthSum", monthSum);
            resList.add(resMap);

            int i = insertWiFarmplanM(farmCd, year, monthStr, ten1, ten2, ten3, monthSum);
            if (i != 1) {
                throw new RuntimeException("汇总用水计划失败，请联系管理员~001");
            }
        }
        return 1;
    }

    /**
     * 查询农户下地块
     * @param year
     * @param farmCd
     * @return
     */
    @Override
    public List<WiLandBVo> getWiLandBListByFarmCd(String year, String farmCd) {
        List<WiLandBVo> list = wiFarmplanMMapper.getWiLandBListByFarmCd(farmCd);
        //遍历地块
        for (WiLandBVo vo : list) {
            //年度作物id
            String cropCd = vo.getCropCd();
            String CropNm = wiOrgplanMMapper.selcetCropNm(cropCd);
            //定义定额
            BigDecimal planVol = new BigDecimal("0");
            List<WiPeriodY> wiPeriodYList = wiPeriodYMapper.selectWiPeriodListbyCropAndCropCd(year, cropCd);
            //遍历周期定额
            for (WiPeriodY wiPeriodY : wiPeriodYList) {
                planVol = planVol.add(new BigDecimal(vo.getLandSize() + "").multiply(wiPeriodY.getPeriodVol()));
            }
            vo.setPlanVol(planVol);
            vo.setCropNm(CropNm);
        }
        return list;
    }

    /**
     * 导入上一年计划
     * @param year
     * @param farmCd
     * @return
     */
    @Override
    public List<WiFarmplanM> importLastYearPlan(String year, String farmCd) {
        List<WiFarmplanM> farmPlanByPlanYmAndOrgCdList = wiFarmplanMMapper.gteFarmplanMByYearAndFarmCd(year, farmCd);
        if (farmPlanByPlanYmAndOrgCdList.size() == 0) {
            return farmPlanByPlanYmAndOrgCdList;
        } else {
            for (WiFarmplanM vo : farmPlanByPlanYmAndOrgCdList) {
                wiFarmplanMMapper.deleteWiFarmplanMByFarmCdAndPlanYm(farmCd, (Integer.parseInt(year) + 1) + vo.getPlanYm().substring(4, 6));
                WiFarmplanM wiFarmplanM = new WiFarmplanM();
                wiFarmplanM.setFarmCd(farmCd);
                wiFarmplanM.setPlanYm((Integer.parseInt(year) + 1) + vo.getPlanYm().substring(4, 6));

                wiFarmplanM.setFirstPlan(vo.getFirstPlan());
                wiFarmplanM.setFirstCtrl(vo.getFirstCtrl());
                wiFarmplanM.setSecondPlan(vo.getSecondPlan());
                wiFarmplanM.setSecondCtrl(vo.getSecondCtrl());
                wiFarmplanM.setThirdPlan(vo.getThirdPlan());
                wiFarmplanM.setThirdCtrl(vo.getThirdCtrl());
                wiFarmplanM.setMonPlan(vo.getMonPlan());
                wiFarmplanM.setMonCtrl(vo.getMonCtrl());
                //操作人相关信息
                wiFarmplanM.setOperDate(new Date());
                wiFarmplanM.setLastId(SecurityUtils.getUserId() + "");
                int i = wiFarmplanMMapper.insertWiFarmplanM(wiFarmplanM);
                if (i == 1) {
                    caleOrgPlan(farmCd,(Integer.parseInt(year) + 1) + vo.getPlanYm().substring(4, 6));
                }
            }
            return wiFarmplanMMapper.gteFarmplanMByYearAndFarmCd((Integer.parseInt(year) + 1) + "", farmCd);
        }
    }

    private int insertWiFarmplanM(String farmCd, String year, String monthStr, BigDecimal ten1, BigDecimal ten2, BigDecimal ten3, BigDecimal monthSum) {
        WiFarmplanM wiFarmplanM = new WiFarmplanM();
        wiFarmplanM.setFarmCd(farmCd);
        wiFarmplanM.setPlanYm(year + monthStr);
        //判断是否已经存在计划，若存在则删除后重新添加汇总数据
        List<WiFarmplanM> wiOrgplanMS = wiFarmplanMMapper.selectWiFarmplanMList(wiFarmplanM);
        if (wiOrgplanMS.size() > 0) {
            wiFarmplanMMapper.deleteWiFarmplanMByFarmCdAndPlanYm(farmCd, year + monthStr);
        }
        wiFarmplanM.setFirstPlan(ten1);
        wiFarmplanM.setFirstCtrl(ten1);
        wiFarmplanM.setSecondPlan(ten2);
        wiFarmplanM.setSecondCtrl(ten2);
        wiFarmplanM.setThirdPlan(ten3);
        wiFarmplanM.setThirdCtrl(ten3);
        wiFarmplanM.setMonPlan(monthSum);
        wiFarmplanM.setMonCtrl(monthSum);
        //操作人相关信息
        wiFarmplanM.setOperDate(new Date());
        wiFarmplanM.setLastId(SecurityUtils.getUserId() + "");
        int i = wiFarmplanMMapper.insertWiFarmplanM(wiFarmplanM);
        //按农户核定定额后，要根据农户定额重新统计机构定额 start
        if (i == 1) {
            caleOrgPlan(farmCd,year + monthStr);
        }
        return i;
    }

    /**
     * 防止在农户级做计划 机构计划不更新
     * 说明：如果按农户做了计划，将整体按农户统计机构计划，若按机构做计划，则直接使用机构计划。
     * 来回操作，计划相互覆盖
     * @param farmCd
     * @param ym
     */
    private void caleOrgPlan(String farmCd,String ym){
        /**汇总当月所有农户的计划用水，更新进机构用水计划*/
        //查询农户所属机构
        String orgCd = wiFarmplanMMapper.selectOrgCdByFarmCd(farmCd);
        WiFarmplanM sumData = wiFarmplanMMapper.farmPlanSumByPlanYm(ym, orgCd);
        wiOrgplanMMapper.deleteWiOrgplanMByOrgCds(orgCd, ym);
        WiOrgplanM wiOrgplanM = new WiOrgplanM();
        wiOrgplanM.setOrgCd(orgCd);
        wiOrgplanM.setPlanYm(ym);
        wiOrgplanM.setFirstCtrl(sumData.getFirstCtrl());
        wiOrgplanM.setFirstPlan(sumData.getFirstPlan());
        wiOrgplanM.setSecondCtrl(sumData.getSecondCtrl());
        wiOrgplanM.setSecondPlan(sumData.getSecondPlan());
        wiOrgplanM.setThirdCtrl(sumData.getThirdCtrl());
        wiOrgplanM.setThirdPlan(sumData.getThirdPlan());
        wiOrgplanM.setMonCtrl(sumData.getMonCtrl());
        wiOrgplanM.setMonPlan(sumData.getMonPlan());
        wiOrgplanM.setLastId(SecurityUtils.getUserId() + "");
        wiOrgplanM.setOperDate(new Date());
        wiOrgplanMMapper.insertWiOrgplanM(wiOrgplanM);
        //按农户核定定额后，要根据农户定额重新统计机构定额 end
    }
}
